﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_GL_TRANSFORM_FEEDBACK_H
#define _UXS_GL_TRANSFORM_FEEDBACK_H

#pragma once

#include "GLStateManager.h"
#include "GLObjectManager.h"

namespace UX_STL
{
namespace GLShell
{

	//
	// Transform Freedback
	//

	class UX_EXPORT GLTransformFeedback : public GLBaseObject
	{
	private:
		GLuint	_uID;

	public:
		GLTransformFeedback();
		GLTransformFeedback(GLTransformFeedback &);
		~GLTransformFeedback();
		
		// for version 3.3
		void  Begin(gl_primitive::type eMode) const;
		void  End()		const;

		GLuint			Id()	const		{ return _uID; }
		static GLenum	Target()			{ return GL_TRANSFORM_FEEDBACK; }


		// for version 4.1
		bool  Create();
		void  Destroy();
		void  Bind() const;
		void  Unbind() const;
		void  Pause()	const;
		void  Resume()	const;
		
		void  Draw(gl_primitive::type eMode) const;
		void  DrawStream(gl_primitive::type eMode, GLuint uStream = 0) const;

		// for version 4.2
		void  DrawInstanced(gl_primitive::type eMode, uint uCount) const;
		void  DrawStreamInstanced(gl_primitive::type eMode, GLuint uStream, uint uCount) const;
	};
	
	
/*
=================================================
	конструктор
=================================================
*/
	inline GLTransformFeedback::GLTransformFeedback(): _uID(0)
	{
	}

	inline GLTransformFeedback::GLTransformFeedback(GLTransformFeedback &cTFB): _uID(cTFB._uID)
	{
		cTFB._uID = 0;
	}
		
/*
=================================================
	деструктор
=================================================
*/
	inline GLTransformFeedback::~GLTransformFeedback()
	{
		if ( _uID != 0 ) {
			GLOM()->DeleteTransformFeedbacks( 1, &_uID );
			_uID = 0;
		}
	}
	
/*
=================================================
	устанавливает текущим (v4.1)
=================================================
*/
	inline void GLTransformFeedback::Bind() const
	{
		SMAN()->BindTransformFeedback( _uID );
	}
	
	inline void GLTransformFeedback::Unbind() const
	{
		SMAN()->BindTransformFeedback( 0 );
	}
	
/*
=================================================
	создать transform feedback (v4.1)
=================================================
*/
	inline bool GLTransformFeedback::Create()
	{
		Destroy();
		return GLOM()->GenTransformFeedbacks( 1, &_uID );
	}
	
/*
=================================================
	удалить (v4.1)
=================================================
*/
	inline void GLTransformFeedback::Destroy()
	{
		if ( _uID != 0 ) {
			GLOM()->DeleteTransformFeedbacks( 1, &_uID );
			_uID = 0;
		}
	}
	
/*
=================================================
	рисовать примитивы (v4.1)
=================================================
*/
	inline void GLTransformFeedback::Draw(gl_primitive::type eMode) const
	{
		SMAN()->DrawTransformFeedback( eMode, _uID );
	}
	
	inline void GLTransformFeedback::DrawInstanced(gl_primitive::type eMode, uint uCount) const
	{
		SMAN()->DrawTransformFeedbackInstanced( eMode, _uID, uCount );
	}
	
/*
=================================================
	рисовать примитивы из потока (v4.1)
=================================================
*/
	inline void GLTransformFeedback::DrawStream(gl_primitive::type eMode, GLuint uStream) const
	{
		SMAN()->DrawTransformFeedbackStream( eMode, _uID, uStream );
	}

	inline void GLTransformFeedback::DrawStreamInstanced(gl_primitive::type eMode, GLuint uStream, uint uCount) const
	{
		SMAN()->DrawTransformFeedbackStreamInstanced( eMode, _uID, uStream, uCount );
	}

/*
=================================================
	начать запись примитивов (v3.3)
=================================================
*/
	inline void GLTransformFeedback::Begin(gl_primitive::type eMode) const
	{
		/*
			only GL_POINTS, GL_LINES, GL_TRIANGLES are supporeted
		*/
		ASSERT( eMode == gl_primitive::POINT or
				eMode == gl_primitive::LINE	 or
				eMode == gl_primitive::TRIANGLE );

		GL_CALL( glBeginTransformFeedback( eMode ) );
	}
	
/*
=================================================
	приостановить запись примитивов (v4.1)
=================================================
*/
	inline void GLTransformFeedback::Pause() const
	{
		GL_CALL( glPauseTransformFeedback() );
	}
	
/*
=================================================
	возобновить запись примитивов (v4.1)
=================================================
*/
	inline void GLTransformFeedback::Resume() const
	{
		GL_CALL( glResumeTransformFeedback() );
	}
	
/*
=================================================
	закончить запись примитивов (v3.3)
=================================================
*/
	inline void GLTransformFeedback::End() const
	{
		GL_CALL( glEndTransformFeedback() );
	}

//-------------------------------------------------------------------

}	// GLShell
}	// UX_STL

#endif	// _UXS_GL_TRANSFORM_FEEDBACK_H